package org.rcy.framework.security.authentication.provider;

import org.rcy.framework.security.exception.Assertion;
import org.rcy.framework.api.security.GrantedRole;
import org.rcy.framework.api.security.SecurityUser;
import org.rcy.framework.api.security.UserPrincipal;
import org.rcy.framework.api.security.UserRolePrincipal;
import org.rcy.framework.security.authentication.AuthenticationToken;
import org.rcy.framework.security.authentication.CredentialsToken;
import org.rcy.framework.security.exception.UserNotFoundException;
import org.rcy.framework.security.principal.UserProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 吴康桥
 * @Description
 * @date 2022/10/28 10:41
 */


public abstract class AbstractAuthenticationProvider implements AuthenticationProvider {
	protected Logger logger = LoggerFactory.getLogger(this.getClass());

	public AbstractAuthenticationProvider() {
	}

	public SecurityUser loadUser(Assertion assertion) throws UserNotFoundException {
		if (assertion != null && assertion.getValue() != null) {
			return this.getUserProvider().loadUser(assertion.getValue());
		} else {
			throw new UserNotFoundException("assertion is null or assertion.getValue() is null");
		}
	}

	public UserPrincipal loadFinalUser(SecurityUser securityUser) {
		return this.getUserProvider().postLoadUser(securityUser);
	}

	protected Authentication createSuccessAuthentication(UserPrincipal finalUser, CredentialsToken authentication) {
		List<SimpleGrantedAuthority> authorities = new ArrayList();
		((List)authorities).add(new SimpleGrantedAuthority("USER"));
		if (finalUser instanceof UserRolePrincipal) {
			UserRolePrincipal userRole = (UserRolePrincipal)finalUser;
			Collection<GrantedRole> roles = userRole.getGrantedRoles();
			if (roles != null && !roles.isEmpty()) {
				authorities = (List)roles.stream().map((role) -> {
					return new SimpleGrantedAuthority(role.getKey());
				}).collect(Collectors.toList());
			}
		}
		return new AuthenticationToken(finalUser, authentication, (Collection)authorities);
	}

	public abstract UserProvider getUserProvider();
}
